﻿
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;


namespace BoilenEditor.Primitives.Snippets {

    [DebuggerDisplay( "SetMemberData: Name={Name}, Type={TypeName}, Method={Method}, Value={Value}" )]
    public partial class SetMemberData {

        private static readonly Dictionary<Type, ReadOnlyCollection<string>> TypeEntries = new Dictionary<Type, ReadOnlyCollection<string>>( );


        public StringBuilder AppendTo( StringBuilder sb ) {
            string value = Ex.GetValueString( this.Value, this.Type );
            return sb
                .Append( Ex.TabString )
                .Append( Ex.TabString )
                .Append( '.' )
                .Append( this.Method.Name.Replace( "PART_", "" ) )
                .Append( "( " )
                .Append( value )
                .AppendLine( " )" );
        }


        private static string GetTypeName( Type type ) {
            return type.GetTypeName( );
        }

        private static bool GetIsEditable( Type type ) {
            return !IsFixedType( type );
        }

        private static bool IsFixedType( Type type ) {
            bool isFixed =
                   type.IsEnum
                || type == typeof( bool );
            return isFixed;
        }

        private static ReadOnlyCollection<string> GetEntries( Type type, MethodInfo declaringMethod ) {
            var defaultValue = declaringMethod.GetCustomAttribute<DefaultValueAttribute>( ).GetValueOrDefault( a => a.Value, null );
            bool isSelectiveFlagsEnum =
                   type.GetCustomAttribute<FlagsAttribute>( ).HasValue( )
                && defaultValue is string;

            ReadOnlyCollection<string> typeEntries;
            if( !TypeEntries.TryGetValue( type, out typeEntries ) ) {
                if( isSelectiveFlagsEnum )
                    typeEntries = defaultValue.ToString( ).Split( ',' ).ToReadOnlyCollection( );
                else if( type.IsEnum )
                    typeEntries = Enum.GetNames( type ).ToReadOnlyCollection( );
                else if( type == typeof( bool ) )
                    typeEntries = new[] { false, true }.Select( e => e.ToString( ) ).ToReadOnlyCollection( );
                else
                    typeEntries = Enumerable.Empty<string>( ).ToReadOnlyCollection( );

                TypeEntries[type] = typeEntries;
            }

            if( defaultValue.HasValue( ) && !isSelectiveFlagsEnum ) {
                string value = (defaultValue ?? "").ToString( );

                var listEntries = typeEntries.ToList( );
                listEntries.Remove( value );
                listEntries.Insert( 0, value );

                typeEntries = listEntries.ToReadOnlyCollection( );
            }

            return typeEntries;
        }

    }

}
